package utils;

import com.google.gson.Gson;
import entity.BPNN;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 工具类
 *
 * @author liangfuqiang
 * @since 2023-03-14
 */
public class FileUtil {
    public static final String RESOURCES = "src/main/resources/";
    private static final Gson GSON = new Gson();
    private static final DateTimeFormatter PATTERN = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    public static <T> T readFile(Class<T> tClass, String fileName, String path) {
        String s;
        try {
            s = Files.readString(Paths.get(path, fileName), StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        return GSON.fromJson(s, tClass);
    }

    public static void writeFile(Object o, String fileName, String path) {
        try {
            Files.writeString(Paths.get(path, fileName), GSON.toJson(o), StandardOpenOption.CREATE_NEW);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    public static BPNN read() {
        File[] files = new File(RESOURCES + "result").listFiles();
        Arrays.sort(files, File::compareTo);
        if (files.length > 0) {
            File file = files[files.length - 1];
            return readFile(BPNN.class, file.getName(), file.getParent());
        } else {
            return null;
        }
    }

    public static void save(int loop, BPNN bpnn) {
        writeFile(bpnn, getNow() + String.format("_%05d", loop) + ".json", RESOURCES + "result");
    }

    public static String getNow() {
        return LocalDateTime.now().format(PATTERN);
    }

    public static double[][] getColor(BufferedImage image) {
        double[][] res = new double[image.getWidth() * image.getHeight()][1];
        for (int i = 0; i < image.getHeight(); i++) {
            for (int j = 0; j < image.getWidth(); j++) {
                int rgb = image.getRGB(i, j);
                int b = rgb & 0x000000ff;
                int g = (rgb >> 8) & 0x000000ff;
                int r = (rgb >> 16) & 0x000000ff;
                res[i * image.getWidth() + j] = new double[]{(b + g + r) / (3.0 * 255)};
            }
        }
        return res;
    }

    public static final Map<Integer, double[][]> MAP = new HashMap<>(50000);

    public static double[][] getColor(File file) {
        try {
            int hashCode = file.hashCode();
            if (!MAP.containsKey(hashCode)) {
                double[][] color = getColor(ImageIO.read(file));
                MAP.put(hashCode, color);
            }
            return MAP.get(hashCode);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
